#include "singleapplication.h"
#include <QtNetwork/QLocalSocket>
#include <QFileInfo>
#include <exception>
#include <QDebug>
#include <QException>
#include "mylogger.h"

#define TIME_OUT (500) // 500ms

using namespace ns_yht;

SingleApplication::SingleApplication(int &argc, char **argv)
    : QCoreApplication(argc, argv), _isRunning(false), _localServer(NULL)
{

    // 取应用程序名作为LocalServer的名字
    _serverName = QFileInfo(QCoreApplication::applicationFilePath()).fileName();

    _initLocalConnection();
}

////////////////////////////////////////////////////////////////////////////////
// 说明：
// 检查是否已經有一个实例在运行, true - 有实例运行， false - 没有实例运行
////////////////////////////////////////////////////////////////////////////////
bool SingleApplication::isRunning()
{
    return _isRunning;
}

////////////////////////////////////////////////////////////////////////////////
// 说明：
// 通过socket通讯实现程序单实例运行，监听到新的连接时触发该函数
////////////////////////////////////////////////////////////////////////////////
void SingleApplication::_newLocalConnection()
{
    QLocalSocket *socket = _localServer->nextPendingConnection();
    if (socket)
    {
        socket->waitForReadyRead(2 * TIME_OUT);
        delete socket;

        // 其他处理，如：读取启动参数
        _activateWindow();
    }
}

////////////////////////////////////////////////////////////////////////////////
// 说明：
// 通过socket通讯实现程序单实例运行，
// 初始化本地连接，如果连接不上server，则创建，否则退出
////////////////////////////////////////////////////////////////////////////////
void SingleApplication::_initLocalConnection()
{
    _isRunning = false;

    QLocalSocket socket;
    socket.connectToServer(_serverName);
    if (socket.waitForConnected(TIME_OUT))
    {
        // fprintf(stderr, "%s already running.\n", _serverName.toLocal8Bit().constData());
        if (GLOG)
            GLOG->info("An instance is running...");
        else
            qInfo() << "An instance is running...";
        _isRunning = true;
        // 其他处理，如：将启动参数发送到服务端
        this->exit(0);
        return;
    }

    // 连接不上服务器，就创建一个
    _newLocalServer();
}

////////////////////////////////////////////////////////////////////////////////
// 说明：
// 创建LocalServer
////////////////////////////////////////////////////////////////////////////////
void SingleApplication::_newLocalServer()
{
    _localServer = new QLocalServer(this);
    connect(_localServer, SIGNAL(newConnection()), this, SLOT(_newLocalConnection()));
    if (!_localServer->listen(_serverName))
    {
        // 此时监听失败，可能是程序崩溃时,残留进程服务导致的,移除之
        if (_localServer->serverError() == QAbstractSocket::AddressInUseError)
        {
            QLocalServer::removeServer(_serverName); // <-- 重点
            _localServer->listen(_serverName);       // 再次监听
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
// 说明：
// 激活主窗口
////////////////////////////////////////////////////////////////////////////////
void SingleApplication::_activateWindow()
{
    // if (w)
    // {
    //     w->show();
    //     w->raise();
    //     w->activateWindow(); // 激活窗口
    // }
}

bool SingleApplication::notify(QObject *receiver, QEvent *event)
{
    bool done = true;
    QT_TRY
    {
        done = QCoreApplication::notify(receiver, event);
    }
    QT_CATCH(QException ex)
    {
        if (GLOG)
            GLOG->info("unexpected error!============================ {}", ex.what());
        else
            qInfo() << "unexpected error!============================" << ex.what();
    }
    QT_CATCH(...)
    {
        if (GLOG)
            GLOG->info("unexpected error!============================type: {},receiver objectName:{}", event->type(), receiver->objectName().toStdString());
        else
            qInfo() << "unexpected error!============================type:" << event->type() << "  receiver objectName:" << receiver->objectName();
    }
    return done;
}